package com.sunrise.financeiro.repositorio;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.sunrise.financeiro.repositorio.iface.DespesaDao;
import com.sunrise.generico.acesso.DaoService;
import com.sunrise.generico.entidade.Despesa;
import com.sunrise.generico.visao.Filtro;

@Repository
public class DespesaDaoImpl extends DaoService<Despesa> implements DespesaDao {

	public List<Despesa> listarOrdenado() {
		List<Despesa> list = listar(Despesa.class);
		Collections.sort(list, new Comparator<Despesa>() {

			@Override
			public int compare(Despesa o1, Despesa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	public List<Despesa> search(Despesa ex) {
		List<Despesa> list = searchByExample(Despesa.class, ex);
		Collections.sort(list, new Comparator<Despesa>() {

			@Override
			public int compare(Despesa o1, Despesa o2) {
				return o1.getNome().compareTo(o2.getNome());
			}
		});
		return list;
	}

	public Despesa getById(Long id) {
		return getById(id, Despesa.class);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Despesa> listarPorNome(String nome) {
		Criteria crit = getSession().createCriteria(Despesa.class);
		crit.add(Restrictions.ilike("nome", nome, MatchMode.ANYWHERE));
		return crit.list();
	}

	@SuppressWarnings("unchecked")
	@Override
	public Collection<Despesa> buscarPorFiltros(Filtro filtro) {
		Criteria crit = getSession().createCriteria(Despesa.class);
		if (filtro.getNome() != null) {
			crit.add(Restrictions.ilike("nome", filtro.getNome(), MatchMode.ANYWHERE));
		}

		if (filtro.getTipoMovimentacaoFinanceira() != null) {
			crit.add(Restrictions.eq("tipoMovimentacaoFinanceira", filtro.getTipoMovimentacaoFinanceira()));
		}

		if (filtro.getCategoriaFinanceira() != null && filtro.getCategoriaFinanceira() != 0) {
			crit.createAlias("categoriaFinanceira", "cat");
			crit.add(Restrictions.eq("cat.id", filtro.getCategoriaFinanceira()));
		}

		if (filtro.getConta() != null && filtro.getConta() != 0) {
			crit.createAlias("conta", "cont");
			crit.add(Restrictions.eq("cont.id", filtro.getConta()));
		}

		if (filtro.getAtivo() != null) {
			crit.add(Restrictions.eq("ativo", filtro.getAtivo().getCodigo()));
		}

		crit.addOrder(Order.asc("nome"));
		return crit.list();
	}

	@Override
	public Despesa buscarPorNome(String nome) {
		Criteria crit = getSession().createCriteria(Despesa.class);
		crit.add(Restrictions.eq("nome", nome).ignoreCase());
		crit.add(Restrictions.eq("ativo", Boolean.TRUE));
		return (Despesa) crit.uniqueResult();
	}

	@Override
	public BigDecimal buscarSomaPorFiltroSemRecorrencia(Date dataInicio, Date dataFim, Long idConta, Long idCategoria) {
		Criteria crit = getSession().createCriteria(Despesa.class).setProjection(Projections.sum("valor"));
		if (dataInicio != null) {
			crit.add(Restrictions.ge("dataLancamento", dataInicio));
		}
		if (dataFim != null) {
			crit.add(Restrictions.le("dataLancamento", dataFim));
		}
		if (idConta != null && idConta != 0) {
			crit.createAlias("conta", "cont");
			crit.add(Restrictions.eq("cont.id", idConta));
		}

		if (idCategoria != null && idCategoria != 0) {
			crit.createAlias("categoriaFinanceira", "cat");
			crit.add(Restrictions.eq("cat.id", idCategoria));

		}
		
		crit.add(Restrictions.eq("recorrencia", false));

		return (BigDecimal) crit.uniqueResult();
	}

}
